# 性能监控工具
import time
import psutil
import logging
from django.db import connection
from django.core.cache import cache
from django.conf import settings
from django.utils import timezone
from functools import wraps
from contextlib import contextmanager
import threading
from collections import defaultdict, deque
import json

logger = logging.getLogger(__name__)


class PerformanceMonitor:
    """性能监控器"""
    
    def __init__(self):
        self.metrics = defaultdict(list)
        self.query_stats = defaultdict(int)
        self.cache_stats = defaultdict(int)
        self.request_times = deque(maxlen=1000)  # 保留最近1000个请求
        self._lock = threading.Lock()
    
    def record_query_time(self, query_time, query_type='unknown'):
        """记录查询时间"""
        with self._lock:
            self.metrics['query_times'].append({
                'time': query_time,
                'type': query_type,
                'timestamp': timezone.now()
            })
            self.query_stats[query_type] += 1
    
    def record_cache_hit(self, cache_key, hit=True):
        """记录缓存命中情况"""
        with self._lock:
            if hit:
                self.cache_stats['hits'] += 1
            else:
                self.cache_stats['misses'] += 1
            
            self.metrics['cache_operations'].append({
                'key': cache_key,
                'hit': hit,
                'timestamp': timezone.now()
            })
    
    def record_request_time(self, request_time, path, method='GET'):
        """记录请求响应时间"""
        with self._lock:
            request_data = {
                'time': request_time,
                'path': path,
                'method': method,
                'timestamp': timezone.now()
            }
            self.request_times.append(request_data)
            self.metrics['request_times'].append(request_data)
    
    def get_system_metrics(self):
        """获取系统指标"""
        try:
            cpu_percent = psutil.cpu_percent(interval=1)
            memory = psutil.virtual_memory()
            disk = psutil.disk_usage('/')
            
            return {
                'cpu_percent': cpu_percent,
                'memory_percent': memory.percent,
                'memory_used': memory.used,
                'memory_total': memory.total,
                'disk_percent': disk.percent,
                'disk_used': disk.used,
                'disk_total': disk.total,
                'timestamp': timezone.now()
            }
        except Exception as e:
            logger.error(f"获取系统指标失败: {e}")
            return {}
    
    def get_database_metrics(self):
        """获取数据库指标"""
        try:
            # 获取数据库连接数
            db_queries = len(connection.queries)
            
            # 计算平均查询时间
            if self.metrics['query_times']:
                recent_queries = [q for q in self.metrics['query_times'] 
                                if (timezone.now() - q['timestamp']).seconds < 300]  # 最近5分钟
                avg_query_time = sum(q['time'] for q in recent_queries) / len(recent_queries) if recent_queries else 0
            else:
                avg_query_time = 0
            
            return {
                'total_queries': db_queries,
                'query_stats': dict(self.query_stats),
                'avg_query_time': avg_query_time,
                'slow_queries': [q for q in self.metrics['query_times'] if q['time'] > 1.0],  # 超过1秒的查询
                'timestamp': timezone.now()
            }
        except Exception as e:
            logger.error(f"获取数据库指标失败: {e}")
            return {}
    
    def get_cache_metrics(self):
        """获取缓存指标"""
        try:
            total_operations = self.cache_stats['hits'] + self.cache_stats['misses']
            hit_rate = (self.cache_stats['hits'] / total_operations * 100) if total_operations > 0 else 0
            
            return {
                'hits': self.cache_stats['hits'],
                'misses': self.cache_stats['misses'],
                'hit_rate': round(hit_rate, 2),
                'total_operations': total_operations,
                'timestamp': timezone.now()
            }
        except Exception as e:
            logger.error(f"获取缓存指标失败: {e}")
            return {}
    
    def get_request_metrics(self):
        """获取请求指标"""
        try:
            if not self.request_times:
                return {}
            
            request_times = [r['time'] for r in self.request_times]
            avg_response_time = sum(request_times) / len(request_times)
            max_response_time = max(request_times)
            min_response_time = min(request_times)
            
            # 按路径统计
            path_stats = defaultdict(list)
            for req in self.request_times:
                path_stats[req['path']].append(req['time'])
            
            slow_requests = [r for r in self.request_times if r['time'] > 2.0]  # 超过2秒的请求
            
            return {
                'total_requests': len(self.request_times),
                'avg_response_time': round(avg_response_time, 3),
                'max_response_time': round(max_response_time, 3),
                'min_response_time': round(min_response_time, 3),
                'slow_requests_count': len(slow_requests),
                'path_stats': {path: {
                    'count': len(times),
                    'avg_time': round(sum(times) / len(times), 3)
                } for path, times in path_stats.items()},
                'timestamp': timezone.now()
            }
        except Exception as e:
            logger.error(f"获取请求指标失败: {e}")
            return {}
    
    def get_comprehensive_report(self):
        """获取综合性能报告"""
        return {
            'system': self.get_system_metrics(),
            'database': self.get_database_metrics(),
            'cache': self.get_cache_metrics(),
            'requests': self.get_request_metrics(),
            'generated_at': timezone.now()
        }
    
    def clear_metrics(self):
        """清除指标数据"""
        with self._lock:
            self.metrics.clear()
            self.query_stats.clear()
            self.cache_stats.clear()
            self.request_times.clear()


# 全局性能监控实例
performance_monitor = PerformanceMonitor()


def monitor_query_time(query_type='unknown'):
    """查询时间监控装饰器"""
    def decorator(func):
        @wraps(func)
        def wrapper(*args, **kwargs):
            start_time = time.time()
            try:
                result = func(*args, **kwargs)
                return result
            finally:
                end_time = time.time()
                query_time = end_time - start_time
                performance_monitor.record_query_time(query_time, query_type)
                
                # 记录慢查询
                if query_time > 1.0:
                    logger.warning(f"慢查询检测: {func.__name__} 耗时 {query_time:.3f}秒")
        return wrapper
    return decorator


def monitor_cache_operation(cache_key_func=None):
    """缓存操作监控装饰器"""
    def decorator(func):
        @wraps(func)
        def wrapper(*args, **kwargs):
            # 生成缓存键
            if cache_key_func:
                cache_key = cache_key_func(*args, **kwargs)
            else:
                cache_key = f"{func.__name__}_{hash(str(args) + str(kwargs))}"
            
            # 检查缓存
            cached_result = cache.get(cache_key)
            if cached_result is not None:
                performance_monitor.record_cache_hit(cache_key, hit=True)
                return cached_result
            
            # 执行函数并缓存结果
            performance_monitor.record_cache_hit(cache_key, hit=False)
            result = func(*args, **kwargs)
            cache.set(cache_key, result, 300)  # 默认5分钟缓存
            
            return result
        return wrapper
    return decorator


@contextmanager
def monitor_request_time(path, method='GET'):
    """请求时间监控上下文管理器"""
    start_time = time.time()
    try:
        yield
    finally:
        end_time = time.time()
        request_time = end_time - start_time
        performance_monitor.record_request_time(request_time, path, method)


class PerformanceMiddleware:
    """性能监控中间件"""
    
    def __init__(self, get_response):
        self.get_response = get_response
    
    def __call__(self, request):
        start_time = time.time()
        
        response = self.get_response(request)
        
        end_time = time.time()
        request_time = end_time - start_time
        
        # 记录请求性能
        performance_monitor.record_request_time(
            request_time, 
            request.path, 
            request.method
        )
        
        # 添加性能头部
        response['X-Response-Time'] = f"{request_time:.3f}s"
        
        # 记录慢请求
        if request_time > 2.0:
            logger.warning(f"慢请求检测: {request.method} {request.path} 耗时 {request_time:.3f}秒")
        
        return response


class DatabaseQueryLogger:
    """数据库查询日志记录器"""
    
    def __init__(self):
        self.queries = []
        self.start_time = None
    
    def __enter__(self):
        self.start_time = time.time()
        self.initial_queries = len(connection.queries)
        return self
    
    def __exit__(self, exc_type, exc_val, exc_tb):
        end_time = time.time()
        total_time = end_time - self.start_time
        
        # 获取新执行的查询
        new_queries = connection.queries[self.initial_queries:]
        
        # 记录查询统计
        performance_monitor.record_query_time(total_time, 'database_block')
        
        # 记录详细查询信息
        for query in new_queries:
            query_time = float(query.get('time', 0))
            if query_time > 0.1:  # 记录超过100ms的查询
                logger.info(f"查询耗时: {query_time}s - {query['sql'][:100]}...")


def get_performance_summary():
    """获取性能摘要"""
    try:
        report = performance_monitor.get_comprehensive_report()
        
        # 生成摘要
        summary = {
            'status': 'healthy',
            'issues': [],
            'recommendations': []
        }
        
        # 检查系统资源
        if report['system'].get('cpu_percent', 0) > 80:
            summary['status'] = 'warning'
            summary['issues'].append('CPU使用率过高')
            summary['recommendations'].append('考虑优化CPU密集型操作')
        
        if report['system'].get('memory_percent', 0) > 85:
            summary['status'] = 'warning'
            summary['issues'].append('内存使用率过高')
            summary['recommendations'].append('检查内存泄漏或增加内存')
        
        # 检查数据库性能
        if report['database'].get('avg_query_time', 0) > 0.5:
            summary['status'] = 'warning'
            summary['issues'].append('数据库查询较慢')
            summary['recommendations'].append('优化数据库查询和索引')
        
        # 检查缓存命中率
        if report['cache'].get('hit_rate', 100) < 70:
            summary['status'] = 'warning'
            summary['issues'].append('缓存命中率较低')
            summary['recommendations'].append('优化缓存策略')
        
        # 检查请求响应时间
        if report['requests'].get('avg_response_time', 0) > 1.0:
            summary['status'] = 'warning'
            summary['issues'].append('请求响应时间较长')
            summary['recommendations'].append('优化应用程序性能')
        
        report['summary'] = summary
        return report
        
    except Exception as e:
        logger.error(f"生成性能摘要失败: {e}")
        return {'error': str(e)}


# 性能测试工具
class PerformanceTester:
    """性能测试工具"""
    
    @staticmethod
    def test_database_performance():
        """测试数据库性能"""
        from ..models import Asset
        
        results = {}
        
        # 测试简单查询
        with DatabaseQueryLogger() as logger:
            start_time = time.time()
            Asset.objects.count()
            end_time = time.time()
            results['simple_query'] = end_time - start_time
        
        # 测试复杂查询
        with DatabaseQueryLogger() as logger:
            start_time = time.time()
            Asset.objects.select_related('category', 'department').filter(
                status='in_use'
            )[:100]
            end_time = time.time()
            results['complex_query'] = end_time - start_time
        
        return results
    
    @staticmethod
    def test_cache_performance():
        """测试缓存性能"""
        results = {}
        
        # 测试缓存写入
        start_time = time.time()
        for i in range(100):
            cache.set(f'test_key_{i}', f'test_value_{i}', 60)
        end_time = time.time()
        results['cache_write'] = end_time - start_time
        
        # 测试缓存读取
        start_time = time.time()
        for i in range(100):
            cache.get(f'test_key_{i}')
        end_time = time.time()
        results['cache_read'] = end_time - start_time
        
        # 清理测试数据
        for i in range(100):
            cache.delete(f'test_key_{i}')
        
        return results
